package com.biz.ssm.controller.admin;

import com.alibaba.fastjson.JSON;
import com.biz.ssm.base.Page;
import com.biz.ssm.base.Pageable;
import com.biz.ssm.base.Response;
import com.biz.ssm.domain.Admin;
import com.biz.ssm.domain.AdminRole;
import com.biz.ssm.domain.Role;
import com.biz.ssm.search.AdminSearchBean;
import com.biz.ssm.security.MyUserDetails;
import com.biz.ssm.security.SecurityContextUtils;
import com.biz.ssm.service.AdminRoleService;
import com.biz.ssm.service.AdminService;
import com.biz.ssm.service.RoleAuthorityService;
import com.biz.ssm.service.RoleService;
import com.biz.ssm.utils.JwtUtils;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * 管理
 * @author tupengxiong
 *
 */
@RestController("adminAdminController")
@RequestMapping("/api/admin")
@Slf4j
public class AdminController{

	@Resource
	private AdminService adminService;

	@Resource
	private RoleService roleService;

	@Resource
	private AdminRoleService adminRoleService;

	@Resource
	private RoleAuthorityService roleAuthorityService;

	private static BCryptPasswordEncoder bpe = new BCryptPasswordEncoder();


	@PostMapping("/sign")
	@ApiOperation(value = "登陆", httpMethod = "POST")
	public Response<Object> sign(@RequestBody Admin admin, HttpServletRequest request) {
		try {
			Admin dto = adminService.findByUsername(admin.getUsername());
			Assert.notNull(dto, "用户不存在");
			Assert.isTrue(bpe.matches(admin.getPassword(), dto.getPassword()), "用户名或密码错误");
			Set<SimpleGrantedAuthority> authorities = new HashSet<>();
			authorities.add(new SimpleGrantedAuthority("ROLE_LOGINED"));
			List<AdminRole> adminRoles = this.adminRoleService.findListByAdmin(dto.getId());
			Set<String> roles = new HashSet<>();
			for (AdminRole adminRole : adminRoles) {
				Role role = this.roleService.selectById(adminRole.getRoles());
				if (null != role) {
					List<String> roleAuthorities = roleAuthorityService.getAuthoritysByRole(adminRole.getRoles());
					for (String auString : roleAuthorities) {
						authorities.add(new SimpleGrantedAuthority(auString));
						roles.add(auString);
					}
				}
			}
			MyUserDetails userDetails = new MyUserDetails(dto.getUsername(), dto.getPassword(), authorities);
			userDetails.setId(dto.getId());
			userDetails.setExtraParam(JSON.parseObject(JSON.toJSONString(dto)));
			userDetails.setRoles(roles);
			String token = JwtUtils.createToken(JwtUtils.SECRET, JwtUtils.IIS, JSON.toJSONString(userDetails), 1440);
			userDetails.setToken(token);
			userDetails.setExtraParam(JSON.parseObject(JSON.toJSONString(dto)));
			return Response.respSuccess(userDetails);
		} catch (IllegalArgumentException e) {
			return Response.respFail(e.getMessage());
		} catch (Exception e) {
			log.error("admin sign error username=" + admin.getUsername(), e);
			return Response.respFail("系统开小差了，请稍后再试~");
		}
	}

	/**
	 * 检查用户名是否存在
	 */
    @PreAuthorize("hasAnyRole('admin','adminList')")
	@RequestMapping(value = "/check_username", method = RequestMethod.GET)
	public @ResponseBody
    boolean checkUsername(String username) {
		if (StringUtils.isEmpty(username)) {
			return false;
		}
		if (adminService.usernameExists(username)) {
			return false;
		} else {
			return true;
		}
	}

	/**
	 * 添加
	 */
    @PreAuthorize("hasAnyRole('admin','adminList')")
	@RequestMapping(value = "/init", method = RequestMethod.GET)
	@ResponseBody
	public Response init() {
		Map<String,Object> data = new HashMap<>();
		data.put("roles", roleService.findAll());
		return Response.respSuccess(data);
	}

	/**
	 * 保存
	 */
	@ApiOperation(value = "管理员保存")
    @PreAuthorize("hasAnyRole('admin','adminList')")
	@RequestMapping(value = "/save", method = RequestMethod.POST)
	public @ResponseBody
    Response save(@RequestBody Admin admin) {
		if (adminService.usernameExists(admin.getUsername())) {
			return Response.respFail("用户名已存在~");
		}
		try {
			admin.setPassword(bpe.encode(admin.getPassword()));
			admin.setIsLocked(false);
			admin.setIsEnabled(admin.getIsEnabled());
			admin.setLoginFailureCount(0);
			admin.setLockedDate(null);
			admin.setLoginDate(null);
			admin.setLoginIp(null);
			admin.setDelStatus(Boolean.FALSE);
			admin.setCreateTime(new Date());
			admin.setModifyTime(new Date());
			this.adminService.createAdmin(admin,admin.getRoleIds());
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return Response.respFail("创建管理员出错了~");
		}
		return Response.respSuccess();
	}

	@PostMapping("/info")
	@PreAuthorize("isAuthenticated()")
	public @ResponseBody Response<MyUserDetails> info() {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		MyUserDetails principal = ((MyUserDetails)authentication.getPrincipal());
		return Response.respSuccess(principal);
	}

	@ApiOperation(value = "管理员详情")
	@RequestMapping(value = "/info/{id}", method = RequestMethod.GET)
    @PreAuthorize("hasAnyRole('admin','adminList')")
	@ResponseBody
	public Response info(@PathVariable Long id) {
		Map<String,Object> data = new HashMap<>();
		Admin admin = adminService.selectById(id);
		List<Role> rolesAll = roleService.findAll();
		List<AdminRole> adminRoles = this.adminRoleService.findListByAdmin(id);
		Set<Role> roles = new HashSet<Role>();
		for (AdminRole adminRole : adminRoles) {
			roles.add(this.roleService.selectById(adminRole.getRoles()));
		}
		for(Role r:rolesAll){
			for(Role role:roles){
				if(r.getId().equals(role.getId())){
					r.setSelected(true);
				}
			}
		}
		data.put("roles", rolesAll);
		admin.setPassword(null);
		data.put("admin", admin);
		return Response.respSuccess(data);
	}

	/**
	 * 更新
	 */
	@ApiOperation(value = "管理员更新")
    @PreAuthorize("hasAnyRole('admin','adminList')")
	@RequestMapping(value = "/update", method = RequestMethod.POST)
	public @ResponseBody
    Response update(@RequestBody Admin admin) {
		Admin pAdmin = adminService.selectById(admin.getId());
		if (pAdmin == null) {
			return  Response.respFail("管理员不存在~");
		}
		if (!StringUtils.isEmpty(admin.getPassword())) {
			admin.setPassword(bpe.encode(admin.getPassword()));
		} else {
			admin.setPassword(pAdmin.getPassword());
		}
		admin.setIsLocked(Boolean.FALSE);
		if (pAdmin.getIsLocked() && !admin.getIsLocked()) {
			admin.setLoginFailureCount(0);
			admin.setLockedDate(null);
			admin.setIsLocked(Boolean.FALSE);
		} else {
			admin.setIsLocked(pAdmin.getIsLocked());
			admin.setLoginFailureCount(pAdmin.getLoginFailureCount());
			admin.setLockedDate(pAdmin.getLockedDate());
		}
		admin.setLoginIp(pAdmin.getLoginIp());
		admin.setLoginDate(pAdmin.getLoginDate());
		pAdmin.setRoleIds(admin.getRoleIds());
		pAdmin.setName(admin.getName());
		pAdmin.setMobile(admin.getMobile());
		pAdmin.setEmail(admin.getEmail());
		pAdmin.setAdminType(admin.getAdminType());
		pAdmin.setIsEnabled(admin.getIsEnabled());
		pAdmin.setIsLocked(admin.getIsLocked());
		pAdmin.setLoginFailureCount(admin.getLoginFailureCount());
		pAdmin.setDelStatus(Boolean.FALSE);
		pAdmin.setLockedDate(admin.getLockedDate());
		pAdmin.setUsername(admin.getUsername());
		pAdmin.setPassword(admin.getPassword());
		try {
			adminService.modifyAdmin(pAdmin,pAdmin.getRoleIds());
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return  Response.respFail("更新管理员出错了~");
		}
		return Response.respSuccess();
	}

	@ApiOperation(value = "获取管理员列表")
	@RequestMapping(value = "/list", method = RequestMethod.GET)
	@ResponseBody
    @PreAuthorize("hasAnyRole('admin','adminList')")
	public Response<Page<Admin>>  list(Pageable pageable, AdminSearchBean searchBean){
		pageable.setBaseSearchBean(searchBean);
		Page<Admin> page = adminService.findPage(pageable);
		return Response.respSuccess(page);
	}

	/**
	 * 删除
	 */
	@ApiOperation(value = "删除管理员")
    @PreAuthorize("hasAnyRole('admin','adminList')")
	@RequestMapping(value = "/delete", method = RequestMethod.POST)
	public @ResponseBody
    Response delete(Long[] ids) {
		if (ids.length >= adminService.count()) {
			return Response.respFail("删除管理员出错了~");
		}
		adminService.removeAdmins(ids);
		return Response.respSuccess();
	}

	 /**
	 * 更新
	 */
	@ApiOperation(value = "修改密码")
    @PreAuthorize("isAuthenticated()")
	@RequestMapping(value = "/modifyPassword", method = RequestMethod.POST)
	public @ResponseBody
    Response<Integer> modifyPassword(@RequestParam("opw") String opw, @RequestParam("pw") String pw) {
		Admin pAdmin = SecurityContextUtils.getCurrentUser(Admin.class);
		Admin admin = adminService.selectById(pAdmin.getId());
		Assert.isTrue(bpe.matches(opw, admin.getPassword()), "原密码错误~");
		Admin record = new Admin();
		record.setId(admin.getId());
		record.setPassword(bpe.encode(pw));
		int r = adminService.update(record);
		return Response.respSuccess(r);
	}
}
